package com.syj.qdp.framework.protection.idempotent.core.aop;

import com.syj.qdp.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.syj.qdp.framework.common.exception.util.ServiceExceptionUtil;
import com.syj.qdp.framework.common.util.collection.CollectionUtils;
import com.syj.qdp.framework.protection.idempotent.core.annotations.Idempotent;
import com.syj.qdp.framework.protection.idempotent.core.ops.IdempotentOps;
import com.syj.qdp.framework.protection.idempotent.core.resovler.IdempotentKeyResolver;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

import java.util.List;
import java.util.Map;

/**
 * @author Lyon
 */
@Slf4j
@Aspect
public class IdempotentAspect {

    Map<Class<? extends IdempotentKeyResolver>, IdempotentKeyResolver> keyResolverMap;
    IdempotentOps idempotentOps;

    public IdempotentAspect(List<IdempotentKeyResolver> keyResolvers, IdempotentOps idempotentOps) {
        this.keyResolverMap = CollectionUtils.convertMap(
                keyResolvers, IdempotentKeyResolver::getClass,
                idempotentKeyResolver -> idempotentKeyResolver
        );
        this.idempotentOps = idempotentOps;

    }

    @Before("@annotation(idempotent)")
    public void beforePointCut(JoinPoint joinPoint, Idempotent idempotent) {
        IdempotentKeyResolver keyResolver = keyResolverMap.get(idempotent.resolver());
        String key = keyResolver.bulidKey(joinPoint, idempotent);
        boolean success = idempotentOps.setIfAbsent(key, idempotent);
        if (!success) {
            log.info("[beforeProcess] 存在重复请求，方法[{}] ，参数[{}] , key[{}]", joinPoint.getSignature().toString(), joinPoint.getArgs(), key);
            throw ServiceExceptionUtil.exception(GlobalErrorCodeConstants.REPEATED_REQUESTS.getCode(), idempotent.message());
        }
    }
}
